/**
 * BrandBigData.com Inc.
 * Copyright (c) 2016 All Rights Reserved.
 */
package com.qibao.toolkit;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xumin
 * @version $Id:PythonExecutorFactory.java, v0.1 2017/7/5 9:19 xumin
 */
public class PythonExecutorFactory implements PooledObjectFactory<PythonExecutor> {
    private static final Logger logger = LoggerFactory.getLogger(PythonExecutorFactory.class);
    @Value("${plutus.python.service.port}")
    private Integer initPort;
    private AtomicInteger port;

    @Override
    public PooledObject<PythonExecutor> makeObject() throws Exception {
        for (int i = 0; i < 10; i++) {
            int servicePort = port.getAndIncrement();
            if (port.intValue() >= 65536) {
                logger.warn("端口已经超出65536，重置端口到初始端口");
                port = new AtomicInteger(initPort);
            }
            try {
                PythonExecutor pythonExecutor = new PythonExecutor(servicePort);
                return new DefaultPooledObject<>(pythonExecutor);
            } catch (Exception e) {
                logger.warn("在端口[{}]启动python服务失败,继续尝试下一个端口[{}]", servicePort, port.addAndGet(100));
            }
        }
        throw new RuntimeException("经过多次尝试，任无法启动python服务，请排查问题");
    }

    @Override
    public void destroyObject(PooledObject<PythonExecutor> pooledObject) throws Exception {
        pooledObject.getObject().close();
    }

    @Override
    public boolean validateObject(PooledObject<PythonExecutor> pooledObject) {
        return pooledObject.getObject().isAlive();
    }

    @Override
    public void activateObject(PooledObject<PythonExecutor> pooledObject) throws Exception {

    }

    @Override
    public void passivateObject(PooledObject<PythonExecutor> pooledObject) throws Exception {

    }

    @PostConstruct
    public void init() {
        port = new AtomicInteger(initPort);
    }

}
